<?php
class Cms_Read extends Cms_Abstract
{
	public function getTablesList()
	{
		// Filters
		$session = new Zend_Session_Namespace(__CLASS__);
		if($this->_isPost()) {
			if($this->_getPost('clear', false)) {
				$session->unsetAll();
			} else {
				$session->filters = $this->_getPost('search');
			}
		}
		
		// Data paginated
		$tablesList = $this->getAdapter()->getTablesList($session->filters);
		$tablesList->setCurrentPageNumber($this->_getParam('pagina'))
			->setItemCountPerPage(20)
			->setPageRange(10);
		
		// Columns from this table
//		foreach($tablesList as $key => $table)
//		{
//			$adapter = Cms::factory(
//				'Read', $table['tablename'], $this->getAdapter()->getSchema()
//			);
//			
//			$table['columns'] = $adapter->getAdapter()->getColumnsFromTable();
//			
//			$tablesList->getIterator()->offsetSet($key, $table);
//		}
		return $tablesList;
	}
	
	public function getTableData(array $filters)
	{
		// Pagination of results (performance)
		$allData = $this->getAdapter()->getTableData(
			$filters,
			$this->_getParam('o'),
			strtoupper($this->_getParam('d', 'ASC'))
		);
		
		$allData->setCurrentPageNumber($this->_getParam('pagina'))
			->setItemCountPerPage(20)
			->setPageRange(10);
		
		// Set foreigns and many to many data
		return $this->_setTableDependences($allData);
	}
	
	/**
	 *  Exibicao de registro
	 */
	public function getTableRow()
	{
		$allData = $this->getAdapter()->getTableRow(array(
			$this->_getParam('c') => $this->_getParam('v')
		));
		
		return $this->_setTableDependences(array($allData), 'detail');
	}
	
	private function _setTableDependences($allData, $hideMode = 'normal')
	{
		$columns = $this->getAdapter()->getColumnsFromTable();
		
		// Get foreign keys from table
		$foreigns = array();
		foreach($columns as $column) {
			if(!empty($column['reference'])) {
				$foreigns[$column['column_name']] = $column['reference'];
			}
		}
		
		$ids = array();
		
		foreach($allData as $key => $data)
		{
			// Replace data with same data, but with foreigns replaced by names
			$data = (array)$this->_getForeignData($data, $foreigns);
			
			// Get possibles many to many data
			$data += $this->_getNmsData($data);
			
			// Get the column and value to make actions (edit, show or delete)
			// with it
			$primary = $this->getAdapter()->getPrimaryKey();
			if(!empty($primary) && isset($primary[0])) {
				$column = $primary[0];
			// This table have no primary key
			} else {
				$column = $this->getAdapter()->representativeTableColumn();
			}
			
			// Set id
			$ids[$key] = array(
				'table' => $this->getAdapter()->getTable(),
				'column' => $column,
				'value' => $data[$column]
			);
			
			
			// Unset hidden fields according type of hidden
			$hidden = $this->getAdapter()->getTableParams('hide');
			if(isset($hidden[$hideMode]) && !empty($hidden[$hideMode])) {
				foreach($hidden[$hideMode] as $hide) {
					if(isset($data[$hide])) {
						unset($data[$hide]);
					}
				}
			}
			
			// Replace object if exists
			if($allData instanceof Zend_Paginator) {
				$allData->getIterator()->offsetSet($key, $data);
			} else {
				$allData[$key] = $data;
			}
		}
		
		return array('data' => $allData, 'ids' => $ids);
	}
	
	private function _getForeignData($data, $foreigns)
	{
		// Foreign keys
		foreach($foreigns as $kF => $fieldF)
		{
			if(!empty($data[$kF]))
			{
				$reference = explode(' = ', $fieldF);
				list($schema, $table, $field) = explode('.', $reference[0]);

				// Change adapter
				$db = Cms::factory('Read', $table, $schema);
				
				// Representative column
				$repColumn = $db->getAdapter()->representativeTableColumn();
				
				// Fk reference data
				$fkData = $db->getAdapter()->getTableRow(
					array($field => $data[$kF])
				);

				// Replace the integer of foreign key to the data
				$data[$kF] = array(
					'repCol' => $fkData[$repColumn],
					'table' => $table,
					'ref' => array($field => $data[$kF])
				);
			}
		}
		return $data;
	}
	
	private function _getNmsData($data)
	{
		$result = array();
		
		// Tables that refers to the table in question
		$dependentTables = $this->getAdapter()->getDependentTables();
		
		foreach($dependentTables as $dep)
		{
			// Catalog of reference parameters
			list($tSchema, $tTable, $tColumn) = explode('.', $dep['to']);
			list($fSchema, $fTable, $fColumn) = explode('.', $dep['from']);
			
			// Change adapter
			$db = Cms::factory('Read', $fTable, $fSchema);
			
			// If correspond to a many to many table
			if($db->getAdapter()->isManyToMany())
			{
				// Get columns from NM table
				$nmTableColumns = $db->getAdapter()->getColumnsFromTable();
				
				foreach($nmTableColumns as $column)
				{
					// Every field in the NM table that make reference in other
					// table (foreign keys)
					if(
						($column['column_name'] != $fColumn) &&
						!empty($column['reference'])
					) {
						$reference = explode(' = ', $column['reference']);
						
						list($rSchema, $rTable, $rColumn) = explode(
							'.', $reference[0]
						);
						
						// Adapter for the third table
						$refAdapter = Cms::factory('Read', $rTable, $rSchema);
						
						// Set the field from foreign key to show as value
						$refRepColumn = $refAdapter->getAdapter()
							->representativeTableColumn();
						
						// Data
						$dataNmRef = $db->getAdapter()->getNmData(
							array($fColumn => $data[$tColumn]),
							array(
								'from' => $rTable,
								'schema' => $rSchema,
								'on' => $column['reference']
							)
						);
						
						// Add the values and select just the field to
						// description
						$nmResultData = array();
						foreach($dataNmRef as $nmData)
						{
							// Get column to make possible detail registers
							$primary = $refAdapter->getAdapter()
								->getPrimaryKey();
							if(!empty($primary) && isset($primary[0])) {
								$columnRef = $primary[0];
							// This table have no primary key
							} else {
								$columnRef = $refRepColumn;
							}

							// Mount parameters to be possible detail each reg
							$nmResultData[] = array(
								'repCol' => $nmData[$refRepColumn],
								'table' => $rTable,
								'ref' => array(
									$columnRef => $nmData[$columnRef]
								)
							);
						}
						
						// Add result after all to add empty relations too
						$result[$rTable] = $nmResultData;
					}
				}
			} // End is nm table
		}
		return $result;
	}
	
	public function columnsToSearch($allData)
	{
		foreach($allData as $data)
		{
			$primary = $this->getAdapter()->getPrimaryKey();
			
			// We just wanna the indexes.. ;)
			foreach(array_keys($data) as $field)
			{
				$name = $this->getAdapter()->rename($field, $primary);

				// Columns information
				$info = $this->getAdapter()->getColumnsFromTable($field);
				
				// Remove input[type=text] to search to filters default 
				$defaultFilter = $this->getAdapter()->getTableParams('filter');
				if($defaultFilter != false) {
					foreach(array_keys($defaultFilter) as $dColumn) {
						if($dColumn == $field) {
							$info['type'] = 'defaultFilter';
						}
					}
				}
				
				// Primaries
				if(in_array($field, $primary)) {
					$result['ID'][$field] = array(
						'name' => $name,
						'type' => isset($info['type']) ? $info['type'] : null
					);
				} else {
					$result[$field] = array(
						'name' => $name,
						'type' => isset($info['type']) ? $info['type'] : null
					);
				}
			}
			
			// Stop inside foreach because we want just the first iteration
			return $result;
		}
	}
	
	public function orderColumns($columns)
	{
		if(!empty($columns)) {
			// Order and Direction (ASC|DESC)
			$o = $this->_getParam('o');
			$d = strtoupper($this->_getParam('d', 'ASC'));

			$order = array();
			foreach($columns as $column => $values) {
				if(!empty($values['type'])) {
					$order[$column] = 'ASC';
					if(($o == $column) && ($d == 'ASC')) {
						$order[$column] = 'DESC';
					}
				}
			}
			return $order;
		}
		return false;
	}
}